package weibo4j.crawler;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;

import weibo4j.Comment;
import weibo4j.IDs;
import weibo4j.Paging;
import weibo4j.RateLimitStatus;
import weibo4j.Status;
import weibo4j.User;
import weibo4j.Weibo;
import weibo4j.WeiboException;

public class CrawlerBase extends Thread {
	protected static DateFormat myDateTimeFormat = 
		DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM);
	private Weibo weibo;

	private long sleepTime;
	private long resetTimeInSeconds;
	private long remainingHits;
	protected Object obj;	

	public CrawlerBase() {
		weibo = null;
		//默认请求之前等待3.6秒钟，此值根据每小时100次的限制算得（每次3.6秒），
		//但鉴于日志操作也有等待时间，故此值应能保证请求次数不超限
		sleepTime = 3000;	
		remainingHits = 1000; //当前小时内剩余请求次数
	    resetTimeInSeconds = 3600; //剩余秒数
		obj = new Object();
	}

	public CrawlerBase(Weibo weibo) {
		this.weibo = weibo;
		sleepTime = 3000;
		remainingHits = 1000; //当前小时内剩余请求次数
	    resetTimeInSeconds = 3600; //剩余秒数    
		obj = new Object();
	}	

	protected User getUserInfoByUserId(long userId) throws WeiboException {
		return weibo.showUserByUserId(userId);
	}

	protected User getUserInfoByScreenName(String screenName)
			throws WeiboException {
		return weibo.showUserByScreenName(screenName);
	}
	
	protected List<Status> getPublicTimeLine(int count) throws WeiboException{
		return weibo.getPublicTimeline(count);
	}

	protected List<Comment> getCommentsByStatusId(long statusId) throws WeiboException{
		int page = 1;
		Paging paging = new Paging(page, 200);
		List<Comment> comments = null;
		List<Comment> result = new ArrayList<Comment>();
		
		while(!(comments= weibo.getComments(statusId, paging)).isEmpty())
		{ 
//			for(Comment comm : comments){
//				System.out.println(++i + " " +  comm.toString());
			result.addAll(comments);
			paging.setPage(page++);
		}
		return result;
	}
	
	protected List<Status> getRetweetedStatusByStatusId(long statusId) throws WeiboException{
		List<Status> result = new ArrayList<Status>();
		int page = 1;
		Paging paging = new Paging(page, 200);
		List<Status> statuses = null;

		while(!(statuses= weibo.getRepostTimeline(statusId, paging)).isEmpty())
		{	
//			for(Status status : statuses){
//			System.out.println(++i + " " +  status.toString());
			result.addAll(statuses);
			paging.setPage(page++);
		}
		return result;		
	}
	
	
	protected int[] getAllFriendsIdsByUserId(long userId) {
		ArrayList<Integer> idss = new ArrayList<Integer>();
		int[] res;
		IDs ids = null;
		long cursor = -1;
		if (userId != -1) {
			try {
				ids = weibo.getFriendsIDsByUserId(userId, cursor);
				//super.sleep(50);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			res = ids.getIDs();
			for (int i = 0; i < res.length; i++) {
				idss.add(res[i]);
			}
			//System.err.println("Friends:");
			//System.err.println("cursor " + cursor + " : " + res.length);
			while (ids.hasNext()) {
				cursor = ids.getNextCursor();
				try {
					ids = weibo.getFriendsIDsByUserId(userId, cursor);
					res = ids.getIDs();
					for (int i = 0; i < res.length; i++) {
						idss.add(res[i]);
					}
					//super.sleep(50);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//System.err.println("cursor " + cursor + " : " + res.length);
			}
			System.err.println("Friends Count: " + idss.size());
			res = new int[idss.size()];
			for (int i = 0; i < idss.size(); i++) {
				res[i] = idss.get(i);
			}
			return res;
		} else {
			System.err.println("Fatal error! the user id is not valid.");
			return null;
		}
	}
	
	protected int[] getAllFollowersIdsByUserId(long userId) {
		ArrayList<Integer> idss = new ArrayList<Integer>();
		int[] res;
		IDs ids = null;
		long cursor = -1;
		if (userId != -1) {
			try {
				ids = weibo.getFollowersIDsByUserId(userId, cursor);
				//super.sleep(50);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			res = ids.getIDs();
			for (int i = 0; i < res.length; i++) {
				idss.add(res[i]);
			}
			//System.err.println("Followers:");
			//System.err.println("cursor " + cursor + " : " + res.length);
			while (ids.hasNext()) {
				cursor = ids.getNextCursor();
				try {
					ids = weibo.getFollowersIDsByUserId(userId, cursor);
					res = ids.getIDs();
					for (int i = 0; i < res.length; i++) {
						idss.add(res[i]);
					}
					//super.sleep(50);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//System.err.println("cursor " + cursor + " : " + res.length);				
			}
			System.err.println("Followers Count: " + idss.size());
			res = new int[idss.size()];
			for (int i = 0; i < idss.size(); i++) {
				res[i] = idss.get(i);;
			}
			return res;
		} else {
			System.err.println("Fatal error! the user id is not valid.");
			return null;
		}
	}
	
	protected int[] getAllFriendsIdsByScreenName(String screenName)  {
		ArrayList<Integer> idss = new ArrayList<Integer>();
		int[] res;
		IDs ids = null;
		long cursor = -1;
		if (!screenName.isEmpty()) {
			try {
				ids = weibo.getFriendsIDsByScreenName(screenName, cursor);
				//super.sleep(50);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			res = ids.getIDs();
			for (int i = 0; i < res.length; i++) {
				idss.add(res[i]);
			}
			//System.err.println("cursor" + cursor + " : " + res.length);
			while (ids.hasNext()) {
				cursor = ids.getNextCursor();
				try {
					ids = weibo.getFriendsIDsByScreenName(screenName, cursor);
					res = ids.getIDs();
					for (int i = 0; i < res.length; i++) {
						idss.add(res[i]);
					}
					//super.sleep(50);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//System.err.println("cursor" + cursor + " : " + res.length);
			}
			System.err.println("Friends Count: " + idss.size());
			res = new int[idss.size()];
			for (int i = 0; i < idss.size(); i++) {
				res[i] = idss.get(i);;
			}
			return res;
		} else {
			System.err.println("Fatal error! the screen name is empty.");
			return null;
		}
	}
	
	protected int[] getAllFollowersIdsByScreenName(String screenName) {
		ArrayList<Integer> idss = new ArrayList<Integer>();
		int[] res;
		IDs ids = null;
		long cursor = -1;
		if (!screenName.isEmpty()) {
			try {
				ids = weibo.getFollowersIDsByScreenName(screenName, cursor);
				//super.sleep(50);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			res = ids.getIDs();
			for (int i = 0; i < res.length; i++) {
				idss.add(res[i]);
			}
			//System.err.println("cursor" + cursor + " : " + res.length);
			while (ids.hasNext()) {
				cursor = ids.getNextCursor();
				try {
					ids = weibo.getFollowersIDsByScreenName(screenName, cursor);
					res = ids.getIDs();
					for (int i = 0; i < res.length; i++) {
						idss.add(res[i]);
					}
					//super.sleep(50);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//System.err.println("cursor" + cursor + " : " + res.length);
			}
			System.err.println("Followers Count: " + idss.size());
			res = new int[idss.size()];
			for (int i = 0; i < idss.size(); i++) {
				res[i] = idss.get(i);;
			}
			return res;
		} else {
			System.err.println("Fatal error! the screen name is empty.");
			return null;
		}
	}

	//检查请求限制剩余次数，并根据情况调整访问频度并返回
    protected void adjustFreq() throws WeiboException, InterruptedException {
    	RateLimitStatus rateLimitStatus = weibo.getRateLimitStatus();
        
        //
    	remainingHits = rateLimitStatus.getRemainingHits();
    	resetTimeInSeconds = rateLimitStatus.getResetTimeInSeconds();
        if (remainingHits == 0){
            this.sleepTime = resetTimeInSeconds * 1000;
        }
        else
        {
            //计算
            long sleep = resetTimeInSeconds * 1000 / remainingHits;
            if (sleep <= 0) 
            	sleep = 1;
            sleepTime = sleep;
        }
        Thread.sleep(sleepTime);
    }

    
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
